import { DirectionalLight, AmbientLight } from 'three';
import * as Three from 'three';
import { createSkyTextureAndBox } from './tools/extraMaterials';
import * as TWEEN from '@tweenjs/tween.js';

const daySkyTexture = createSkyTextureAndBox('day').textureCube;
const nightSkyTexture = createSkyTextureAndBox('night').textureCube;

const createDayNightConfig = (daySkyTexture, nightSkyTexture) => ({
  day: {
    skyTexture: daySkyTexture,
    directionalLightIntensity: 1,
    directionalLightPosition: new Three.Vector3(-50, 100, 0),
    ambientLightIntensity: 0.5,
    // shadowEnabled: true,
  },
  night: {
    skyTexture: nightSkyTexture,
    directionalLightIntensity: 0.3,
    directionalLightPosition: new Three.Vector3(5, 100, 0),
    ambientLightIntensity: 0.1,
    // shadowEnabled: true,
  },
});

export default class Light {
  /**
   * @type {Array<DirectionalLight>}
   */
  directionLights = [];

  /**
   * @type {Array<AmbientLight>}
   */
  ambientLights = [];

  currentMode = 'day';
  config;
  isTransitioning = false;

  constructor(option) {
    const { scene, initialMode = 'day' } = option;
    this.scene = scene;
    // 环境光;
    const ambient = new AmbientLight(0xffffff, 2);
    scene.add(ambient);

    // 创建配置对象
    this.config = createDayNightConfig(daySkyTexture, nightSkyTexture);
    // 初始化当前模式
    this.currentMode = initialMode;
    const initialState = this.config[this.currentMode];

    // 创建平行光（太阳光/月光）

    const DayNight_directionalLight = new Three.DirectionalLight(0xffffff, initialState.directionalLightIntensity);
    DayNight_directionalLight.position.copy(initialState.directionalLightPosition);
    DayNight_directionalLight.castShadow = true;
    const dirLightHelper = new Three.DirectionalLightHelper(DayNight_directionalLight, 5, 0xff0000);
    scene.add(dirLightHelper);

    // 创建环境光
    const DayNight_ambientLight = new Three.AmbientLight(0xffffff, initialState.ambientLightIntensity);
    this.DayNight_ambientLight = DayNight_ambientLight;
    scene.add(DayNight_ambientLight);

    // 设置阴影参数
    const DayNight_directionalLightSize = 1000;
    DayNight_directionalLight.shadow.mapSize.width = 2048;
    DayNight_directionalLight.shadow.mapSize.height = 2048;
    DayNight_directionalLight.shadow.camera.near = 0.5;
    DayNight_directionalLight.shadow.camera.far = DayNight_directionalLightSize * 2;
    DayNight_directionalLight.shadow.camera.left = -DayNight_directionalLightSize;
    DayNight_directionalLight.shadow.camera.right = DayNight_directionalLightSize;
    DayNight_directionalLight.shadow.camera.top = DayNight_directionalLightSize;
    DayNight_directionalLight.shadow.camera.bottom = -DayNight_directionalLightSize;

    this.DayNight_directionalLight = DayNight_directionalLight;

    scene.add(DayNight_directionalLight);

    // 设置初始背景
    scene.background = initialState.skyTexture;
  }

  /**
   * TODO:
   * - 优化后应该不需要传入option
   */
  switchDayNight(targetMode) {
    if (this.currentMode === targetMode) return;
    const directionalLight = this.DayNight_directionalLight;
    const ambientLight = this.DayNight_ambientLight;
    const scene = this.scene;

    const startState = {
      skyTexture: scene.background,
      directionalLightIntensity: directionalLight.intensity,
      directionalLightPosition: directionalLight.position.clone(),
      ambientLightIntensity: ambientLight.intensity,
    };

    const targetState = this.config[targetMode];

    // 创建颜色过渡对象
    const colorObj = { r: 0, g: 0, b: 0 };
    if (startState.skyTexture instanceof Three.Color) {
      colorObj.r = startState.skyTexture.r;
      colorObj.g = startState.skyTexture.g;
      colorObj.b = startState.skyTexture.b;
    }

    const targetColor = targetState.skyTexture instanceof Three.Color ? targetState.skyTexture : new Three.Color(0x000000);

    // 创建Tween动画
    new TWEEN.Tween(colorObj)
      .to(
        {
          r: targetColor.r,
          g: targetColor.g,
          b: targetColor.b,
        },
        500
      )
      .easing(TWEEN.Easing.Quadratic.InOut)
      .onUpdate(() => {
        scene.background = new Three.Color(colorObj.r, colorObj.g, colorObj.b);
      })
      .onComplete(() => {
        scene.background = targetState.skyTexture;
      })
      .start();

    // 灯光强度过渡
    new TWEEN.Tween({ val: startState.directionalLightIntensity })
      .to({ val: targetState.directionalLightIntensity }, 500)
      .easing(TWEEN.Easing.Quadratic.InOut)
      .onUpdate((obj) => {
        directionalLight.intensity = obj.val;
      })
      .start();

    // 灯光位置过渡
    new TWEEN.Tween(startState.directionalLightPosition)
      .to(targetState.directionalLightPosition, 500)
      .easing(TWEEN.Easing.Quadratic.InOut)
      .onUpdate((pos) => {
        directionalLight.position.copy(pos);
        // 更新阴影相机位置
        directionalLight.shadow.camera.position.copy(pos);
        directionalLight.shadow.camera.lookAt(scene.position);
        directionalLight.shadow.camera.updateProjectionMatrix();
      })
      .start();

    // 环境光过渡
    new TWEEN.Tween({ val: startState.ambientLightIntensity })
      .to({ val: targetState.ambientLightIntensity }, 500)
      .easing(TWEEN.Easing.Quadratic.InOut)
      .onUpdate((obj) => {
        ambientLight.intensity = obj.val;
      })
      .start();

    // // 阴影开关过渡 (在动画进行到一半时切换)
    // setTimeout(() => {
    //   renderer.shadowMap.enabled = targetState.shadowEnabled;
    // }, 250);

    this.currentMode = targetMode;
  }
}
